#include <bits/stdc++.h>
using namespace std;

template <class T>
void read(T &x)
{
    bool f(0);
    x = 0;
    char ch = getchar();
    while (ch < '0' || ch > '9')
        f ^= ch == '-', ch = getchar();
    while (ch >= '0' && ch <= '9')
        x = (x * 10) + (ch ^ 48), ch = getchar();
    x = f ? -x : x;
}

template <class T, class... ARK>
void read(T &x, ARK &...ark)
{
    read(x);
    read(ark...);
}

#define lowbit(x) ((x) & (-(x)))
#define maxl 1000005
#define maxn 100005

int t, n, m, len, vlim;
int d[maxn], v[maxn], a[maxn], p[maxn];

set<int> st[maxn];

int nodel, noder, nodeval;
struct node
{
    int lzadd, maxv;
    node *left, *right;
    void build(int thisl, int thisr);
    void add(int thisl, int thisr);
    void pushdown();
    void pushup();
    pair<int, int> qmax(int thisl, int thisr);
} root, tree[maxn << 1], *cnt = tree;

struct lis
{
    lis *before, *nxt;
    set<int> *to;
} body[maxn], *liscnt = body + 1;

void lisins(set<int> *i)
{
    (liscnt + 1)->before = liscnt;
    liscnt->nxt = (liscnt + 1);
    liscnt->to = i;
    ++liscnt;
}

void liserase(lis *i)
{
    i->before->nxt = i->nxt;
    i->nxt->before = i->before;
}

inline void init()
{
    for (int i = 1; i <= m; ++i)
        st[i].clear();
    cnt = tree;
    memset(body, 0, sizeof(body));
    body[1].before = body;
    body->nxt = body + 1;
}

int main()
{
    body->nxt = body + 1;
    freopen("detect.in", "r", stdin);
    freopen("detect.out", "w", stdout);
    read(t);
    while (t--)
    {
        init();
        read(n, m, len, vlim);
        for (int i = 1; i <= n; ++i)
        {
            read(d[i], v[i], a[i]);
        }
        for (int i = 1; i <= m; ++i)
            read(p[i]);
        nodeval = 1;
        root.build(1, m);
        int anscnt(0);
        for (int i = 1; i <= n; ++i)
        {
            if (v[i] <= vlim)
            {
                if (a[i] <= 0)
                    continue;
                else
                {
                    d[i] += ceil((vlim * vlim - v[i] * v[i]) / (2. * a[i]));
                    int kl = lower_bound(p + 1, p + m + 1, d[i]) - p;
                    nodel = kl, noder = m;
                    if (kl > m)
                        continue;
                    root.add(1, m);
                    st[kl].insert(m);
                    ++anscnt;
                    // cerr << i << ' ' << nodel << ' ' << noder << endl;
                }
            }
            else // v[i]>vlim
            {
                if (a[i] >= 0)
                {
                    int kl = lower_bound(p + 1, p + m + 1, d[i]) - p;
                    nodel = kl, noder = m;
                    if (kl > m)
                        continue;
                    root.add(1, m);
                    st[kl].insert(m);
                    ++anscnt;
                    // cerr << i << ' ' << nodel << ' ' << noder << endl;
                }
                else
                {
                    int kl = lower_bound(p + 1, p + m + 1, d[i]) - p;
                    int kr = lower_bound(p + 1, p + m + 1,
                                         d[i] + floor((vlim * vlim - v[i] * v[i]) / (2. * a[i]))) -
                             p;
                    nodel = kl, noder = kr;
                    if (kl >= kr)
                        continue;
                    root.add(1, m);
                    st[kl].insert(kr);
                    ++anscnt;
                    // cerr << i << ' ' << nodel << ' ' << noder << endl;
                }
            }
        }
        printf("%d ", anscnt);
        for (int i = 1; i <= m; ++i)
            lisins(st + i);
        int ans(0);
        while (root.maxv)
        {
            ++ans;
            int pos = root.qmax(1, m).first;
            lis *k = body->nxt;
            while (k != liscnt)
            {
                set<int> *p = k->to;
                if (p - st > pos)
                    break;
                for (set<int>::iterator it = (*p).lower_bound(pos); it != (*p).end(); ++it)
                {
                    nodel = p - st;
                    noder = *it;
                    nodeval = -1;
                    root.add(1, m);
                }
                if ((*p).empty())
                    liserase(k);
                k = k->nxt;
            }
        }
        printf("%d\n", m - ans);
    }
    return 0;
}

void node::build(int thisl, int thisr)
{
    lzadd = maxv = 0;
    if (thisl == thisr)
    {
        return;
    }
    int mid((thisl + thisr) >> 1);
    left = cnt++;
    right = cnt++;
    left->build(thisl, mid);
    right->build(mid + 1, thisr);
}

void node::add(int thisl, int thisr)
{
    if (nodel <= thisl && thisr <= noder)
    {
        lzadd += nodeval;
        maxv += nodeval;
        return;
    }
    pushdown();
    int mid((thisl + thisr) >> 1);
    if (nodel <= mid)
        left->add(thisl, mid);
    if (mid < noder)
        right->add(mid + 1, thisr);
    pushup();
}

void node::pushdown()
{
    left->lzadd += lzadd;
    left->maxv += lzadd;
    right->lzadd += lzadd;
    right->maxv += lzadd;
    lzadd = 0;
}

void node::pushup()
{
    maxv = max(left->maxv, right->maxv);
}

pair<int, int> node::qmax(int thisl, int thisr)
{
    if (nodel <= thisl && thisr <= noder)
        return {thisl, maxv};
    int mid((thisl + thisr) >> 1);
    pushdown();
    pair<int, int> ans({0, INT_MIN});
    if (nodel <= mid)
    {
        ans = left->qmax(thisl, mid);
    }
    if (mid < noder)
    {
        auto c = right->qmax(mid + 1, thisr);
        if (c.second > ans.second)
            ans = c;
    }
    return ans;
}